package com.example.common.config.rabbit.kill;

import com.example.common.constant.MessageConstant;
import com.example.common.constant.RabbitContent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.amqp.RabbitProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;

/**
 * <p>
 *      秒杀MQ配置
 * </p>
 *
 * @author zyred
 * @since v 0.1
 **/
@Slf4j
@Configuration
@ConfigurationProperties(prefix = "spring.rabbitmq")
public class SecKillRabbitConfig {

    @Autowired
    private RabbitProperties rabbitProperties;
    @Autowired private RabbitTemplate rabbitTemplate;

    @Bean
    public MessageConverter messageConverter() {
        log.info("Enable jackson2 message converter.");
        return new Jackson2JsonMessageConverter();
    }

    /**
     * 初始化为 rabbitTemplate 设置确认机制
     */
    @PostConstruct
    public void initSetting() {

        // 开启了 broker 消息确认才执行
        if (this.rabbitProperties.isPublisherConfirms()) {
            this.rabbitTemplate.setConfirmCallback(
                    /*
                     * correlationData: 消息唯一关联数据
                     * ack:             消息是否成功收到
                     * cause:           错误发送的原因
                     */
                    (correlationData, ack, cause) -> {
                        log.info(">>>>>>>>>>>>>>>>>>>Broker>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                        if (!ack) {
                            log.info("唯一关联数据：{}", correlationData);
                            log.info("错误发送的原因：{}", cause);
                        }
                        log.info("消息是否成功收到：{}", ack);
                        log.info("<<<<<<<<<<<<<<<<<<<Broker<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
                    }
            );
            log.info("Rabbit publisher confirms enable.");
        } else {
            log.info("Rabbit publisher confirms disable.");
        }

        // 未开启消息抵达通知
        if (!this.rabbitProperties.isPublisherReturns()) {
            log.info("Rabbit publisher returns disable.");
            return;
        }

        // 发送消息成功后是不会触发这里的
        this.rabbitTemplate.setReturnCallback(
                /*
                 * message:     投递失败的消息详情
                 * replyCode:   回复的状态码
                 * replyText:   回复的文本消息
                 * exchange:    使用的交换机名称
                 * routingKey:  使用的路由键名称
                 */

                /*

                消息详情：[]
                状态码：312
                错误消息：NO_ROUTE
                交换机名称：order-event-exchange
                路由键名称：order.create.order.test
                 */
                (message, replyCode, replyText, exchange, routingKey) -> {

                    log.info(">>>>>>>>>>>>>>>>>>>>>Queue>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                    log.info("消息详情：{}", message);
                    log.info("状态码：{}", replyCode);
                    log.info("错误消息：{}", replyText);
                    log.info("交换机名称：{}", exchange);
                    log.info("路由键名称：{}", routingKey);
                    log.info("<<<<<<<<<<<<<<<<<<<<<<Queue<<<<<<<<<<<<<<<<<<<<<<<<<<");

                    // 只要这里一旦触发，那么一定是持久化失败
                    int status = MessageConstant.MessageStatus.PERSISTENCE_ERROR.getCode();
                    // 组装错误原因
                    String reason = "状态码:(" + replyCode + ") 原因:(" + replyText + ")";
                    // 从消息里面拿到错误 ID
                }
        );

        log.info("Rabbit publisher returns enable.");
    }

}
